%%%-------------------------------------------------------------------
%%% @author Rain
%%% @copyright (C) 2022, <COMPANY>
%%% @doc
%%% @end
%%%-------------------------------------------------------------------
-module(obj_svr).

-behaviour(gen_server).
-include("obj.hrl").
-include("tower_aoi.hrl").

-export([start_obj_svr/1, start_link/1]).
-export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2,
    code_change/3]).

-define(SERVER, ?MODULE).

-record(state, {uid = #uid{}}).

%%%===================================================================
%%% Spawning and gen_server implementation
%%%===================================================================

start_obj_svr(UidValue) ->
    ChildSpec = #{id => UidValue,
        start => {?MODULE, start_link, [UidValue]},
        restart => permanent,
        shutdown => 2000,
        type => worker,
        modules => [?MODULE]},
    supervisor:start_child(tower_aoi_app_sup, ChildSpec).

start_link(UidValue) ->
    gen_server:start_link({local, ?OBJ_SVR(UidValue)}, ?MODULE, [UidValue], []).

init([UidValue]) ->
    {ok, #state{uid = #uid{value = UidValue, type = ?UID_TYPE_PLAYER}}}.

handle_call(_Request, _From, State = #state{}) ->
    {reply, ok, State}.

handle_cast(_Request, State = #state{}) ->
    {noreply, State}.

handle_info({enter_map, X, Y}, State = #state{uid = Uid}) ->
    io:format("Uid(~p): 我请求进入了地图的 {~p, ~p} ~n", [Uid#uid.value, X, Y]),
    ok = gen_server:call(tower_aoi_svr, {enter_map, Uid, X, Y}),
    {noreply, State};

handle_info(leave_map, State = #state{uid = Uid}) ->
    io:format("Uid(~p): 我请求离开了地图 ~n", [Uid#uid.value]),
    gen_server:call(tower_aoi_svr, {leave_map, Uid}),
    {noreply, State};

handle_info({sync_map, X, Y}, State = #state{uid = Uid}) ->
    io:format("Uid(~p): 我请求移动到地图的 {~p, ~p} ~n", [Uid#uid.value, X, Y]),
    gen_server:cast(tower_aoi_svr, {sync_map, Uid, X, Y}),
    {noreply, State};

handle_info({appear, #object{uid_value = AppearUid, x = X, y = Y} = _Object}, State = #state{uid = Uid}) ->
    io:format("Uid(~p): 我看到 ~p 在 {~p, ~p} 出现了~n", [Uid#uid.value, AppearUid, X, Y]),
    {noreply, State};

handle_info({disappear, #object{uid_value = DisappearUid} = _Object}, State = #state{uid = Uid}) ->
    io:format("Uid(~p): 我看到 ~p 消失了 ~n", [Uid#uid.value, DisappearUid]),
    {noreply, State};

handle_info({move, #object{uid_value = SyncUid, x = X, y = Y} = _Object}, State = #state{uid = Uid}) ->
    io:format("Uid(~p): 我看到 ~p 移动到了 {~p ~p} ~n", [Uid#uid.value, SyncUid, X, Y]),
    {noreply, State};

handle_info({viewport, Viewport}, State = #state{uid = #uid{value = UidValue}}) ->
    case lists:keyfind(appear, 1, Viewport) of
        {appear, AppearObjects} ->
            [io:format("Uid(~p): 我看到 ~p 在 {~p, ~p} 出现了~n", [UidValue, AppearUid, X, Y])
                ||#object{uid_value = AppearUid, x = X, y = Y}<-AppearObjects];
        _ ->
            pass
    end,
    case lists:keyfind(disappear, 1, Viewport) of
        {disappear, DisappearObjects} ->
            [io:format("Uid(~p): 我看到 ~p 消失了 ~n", [UidValue, DisappearUid])
                ||#object{uid_value = DisappearUid}<-DisappearObjects];
        _ ->
            pass
    end,
    {noreply, State};

handle_info(_Info, State = #state{}) ->
    {noreply, State}.

terminate(_Reason, _State = #state{}) ->
    ok.

code_change(_OldVsn, State = #state{}, _Extra) ->
    {ok, State}.

%%%===================================================================
%%% Internal functions
%%%===================================================================
